﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DHISInteroperability.Authentication;
using DHISInteroperability.DataTransfer;
using System.Collections.Generic;
using System.Linq;

namespace DHISInteroperability.Tests
{
    [TestClass]
    public class DataTransferManagerTest
    {
        [TestMethod]
        public void Sending_Data_Values()
        {
            var agent = new AuthorizationAgent("admin", "district");
            var baseUrl = "https://apps.dhis2.org/demo";
            var data = new dataValueSet();
            data.dataSet = "aLpVgfXiz0f";   // Population
            data.orgUnit = "DiszpKrYNg8";   // Lushoto District Hospital
            data.period = "2014";

            var values = new dataValue[] {
                new dataValue
                {
                    dataElement = "h0xKKjijTdI",    // Expected Pregnancies
                    value = "23"
                },
                new dataValue
                {
                    dataElement = "DTtCy7Nx5jH",    // Total Population < 5 Years
                    value = "29"
                },
                new dataValue
                {
                    dataElement = "DTVRnCGamkV",    // Total Population < 1 Year
                    value = "31"
                },
                new dataValue
                {
                    dataElement = "vg6pdjObxsm",    // Population of Women of Child Bearing Age (WRA)
                    value = "37"
                },
                new dataValue
                {
                    dataElement = "WUg3MYWQ7pt",    // Total Population
                    value = "41"
                },
            };
            data.dataValue = values;

            var transferManager = new DataTransferManager(baseUrl, agent);
            var importSummary = transferManager.SendDataValues(data);

            Assert.IsNotNull(importSummary, "Data import failed");
            Assert.AreEqual(importSummary.STATUS_SUCCESS, importSummary.status, importSummary.description);
            Assert.IsNotNull(importSummary.importCount, "Data import count is inconsistent");
        }

        [TestMethod]
        public void Getting_Data_Values()
        {
            var agent = new AuthorizationAgent("admin", "district");
            //var baseUrl = "http://localhost:8090/dhis";
            var baseUrl = "https://apps.dhis2.org/demo";
            string dataset = "pBOMPrpg1QX";
            string organisationUnit = "YuQRtpLP10I";
            string period = "201401";

            var transferManager = new DataTransferManager(baseUrl, agent);     
            var outputValues = transferManager.GetDataValues(dataset, organisationUnit, period);

            Assert.IsNotNull(outputValues, "Output values can not be null");
            //Assert.AreEqual(3, outputValues.dataValue.Length, "Number of data elements don't match");
        }

        [TestMethod]
        public void Getting_Data_Values_With_Time_Span()
        {
            var agent = new AuthorizationAgent("admin", "district");
            var baseUrl = "https://apps.dhis2.org/demo";
            List<string> datasets = new List<string> { "pBOMPrpg1QX", "BfMAe6Itzgt" };
            List<string> organisationUnits = new List<string> { "YuQRtpLP10I", "vWbkYPRmKyS" };
            string startDate = "2013-01-01";
            string endDate = "2013-01-31";

            var transferManager = new DataTransferManager(baseUrl, agent);
            var outputValues = transferManager.GetDataValues(datasets, organisationUnits, startDate, endDate);

            Assert.IsNotNull(outputValues, "Output values can not be null");
            Assert.AreNotEqual(0, outputValues.dataValue.Length, "There should be atleast one data value");
        }

        [TestMethod]
        public void Sending_Completed_Data_Values()
        {
            var agent = new AuthorizationAgent("admin", "district");
            var baseUrl = "https://apps.dhis2.org/demo";
            string dataset = "aLpVgfXiz0f";             // Population
            string organisationUnit = "DiszpKrYNg8";    // Ngelehun CHC
            string period = "2014";

            var data = new dataValueSet();
            data.dataSet = dataset;   
            data.orgUnit = organisationUnit;  
            data.period = period;

            var values = new dataValue[] {
                new dataValue
                {
                    dataElement = "h0xKKjijTdI",    // Expected Pregnancies
                    value = "231"
                },
                new dataValue
                {
                    dataElement = "DTtCy7Nx5jH",    // Total Population < 5 Years
                    value = "291"
                },
                new dataValue
                {
                    dataElement = "DTVRnCGamkV",    // Total Population < 1 Year
                    value = "311"
                },
                new dataValue
                {
                    dataElement = "vg6pdjObxsm",    // Population of Women of Child Bearing Age (WRA)
                    value = "371"
                },
                new dataValue
                {
                    dataElement = "WUg3MYWQ7pt",    // Total Population
                    value = "411"
                },
            };
            data.dataValue = values;
            data.SetCompleted();

            var transferManager = new DataTransferManager(baseUrl, agent);
            var importSummary = transferManager.SendDataValues(data);

            Assert.IsNotNull(importSummary, "Data import failed");
            Assert.AreEqual(importSummary.STATUS_SUCCESS, importSummary.status, importSummary.description);
            Assert.IsNotNull(importSummary.importCount, "Data import count is inconsistent");

            var dataSetValues = transferManager.GetDataValues(dataset, organisationUnit, period);
            Assert.IsNotNull(dataSetValues, "Error during data retrieval");
            Assert.AreEqual(5, dataSetValues.dataValue.Length);
            Assert.AreEqual(DateTime.Now.ToString("yyyy-MM-dd"), DateTime.Parse(dataSetValues.completeDate).ToString("yyyy-MM-dd"));
        }

        [TestMethod]
        public void Sending_Data_Values_With_Invalid_Dataset()
        {
            Assert.Inconclusive("The test needs to be refined");
            var agent = new AuthorizationAgent("admin", "district");
            var baseUrl = "http://localhost:8090/dhis";
            var data = new dataValueSet();
            data.dataSet = "J6fwKju9vxq";   // Population
            data.orgUnit = "R4wR8AdDdZ8";   // Lushoto District Hospital
            data.period = "201401";

            var values = new dataValue[] {
                new dataValue
                {
                    dataElement = "jHUt9blxKOh",    // Expected Pregnancies
                    value = "23"
                },
                new dataValue
                {
                    dataElement = "DOHWySLNIkN",    // Total Population < 5 Years
                    value = "29"
                },
                new dataValue
                {
                    dataElement = "ZoFk8pYNrGw",    // Total Population < 1 Year
                    value = "31"
                },
                new dataValue
                {
                    dataElement = "ElVPddwVlGD",    // Population of Women of Child Bearing Age (WRA)
                    value = "37"
                },
                new dataValue
                {
                    dataElement = "z7mo9HWxQb9",    // Total Population
                    value = "41"
                },
            };
            data.dataValue = values;

            var transferManager = new DataTransferManager(baseUrl, agent);
            var importSummary = transferManager.SendDataValues(data);

            Assert.IsNotNull(importSummary, "Data import failed");
            Assert.AreEqual(importSummary.STATUS_SUCCESS, importSummary.status, importSummary.description);
            Assert.IsNotNull(importSummary.importCount, "Data import count is inconsistent");
        }

        [TestMethod]
        public void Getting_List_Of_Datasets()
        {
            var agent = new AuthorizationAgent("admin", "district");
            var baseUrl = "https://apps.dhis2.org/demo";

            var transferManager = new DataTransferManager(baseUrl, agent);
            var outputValues = transferManager.GetAllDataSets();

            Assert.IsNotNull(outputValues, "Output values can not be null");
            Assert.AreNotEqual(0, outputValues.Count, "There should be at least one dataset");
        }

        [TestMethod]
        public void Getting_Dataset()
        {
            var agent = new AuthorizationAgent("admin", "district");
            var baseUrl = "https://apps.dhis2.org/demo";
            string datasetId = "aLpVgfXiz0f";   // Population

            var transferManager = new DataTransferManager(baseUrl, agent);
            var outputValues = transferManager.GetDataSet(datasetId);

            Assert.IsNotNull(outputValues, "Output values can not be null");
            Assert.AreEqual(5, outputValues.dataElements.Length, "There should be five data elements");
        }

        [TestMethod]
        public void VerifyingSavedData()
        {
            var agent = new AuthorizationAgent("admin", "district");
            var baseUrl = "https://apps.dhis2.org/demo";
            var data = new dataValueSet();
            data.dataSet = "aLpVgfXiz0f";   // Population
            data.orgUnit = "DiszpKrYNg8";   // Ngelehun CHC
            data.period = "2014";

            // DataValues will be randomly generated
            Random random = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
            var values = new dataValue[] {
                new dataValue
                {
                    dataElement = "h0xKKjijTdI",    // Expected Pregnancies
                    value = random.Next(1, 1000).ToString()
                },
                new dataValue
                {
                    dataElement = "DTtCy7Nx5jH",    // Total Population < 5 Years
                    //value = random.Next(1, 1000).ToString()
                    value = "19870"
                },
                new dataValue
                {
                    dataElement = "DTVRnCGamkV",    // Total Population < 1 Year
                    value = random.Next(1, 1000).ToString()
                },
                new dataValue
                {
                    dataElement = "vg6pdjObxsm",    // Population of Women of Child Bearing Age (WRA)
                    value = random.Next(1, 1000).ToString()
                },
                new dataValue
                {
                    dataElement = "WUg3MYWQ7pt",    // Total Population
                    value = random.Next(1, 1000).ToString()
                },
            };
            data.dataValue = values;

            var transferManager = new DataTransferManager(baseUrl, agent);
            var importSummary = transferManager.SendDataValues(data);

            Assert.IsNotNull(importSummary, "Data import failed");
            Assert.AreEqual(importSummary.STATUS_SUCCESS, importSummary.status, importSummary.description);
            Assert.IsNotNull(importSummary.importCount, "Data import count is inconsistent");

            var outputValues = transferManager.GetDataValues(data.dataSet, data.orgUnit, data.period);
            Assert.IsNotNull(outputValues, "Output values can not be null");
            Assert.AreEqual(5, outputValues.dataValue.Length, "Number of data elements don't match");

            var originalValues = data.dataValue.ToList();
            foreach (var freshValue in outputValues.dataValue)
            {
                bool found = false;
                foreach (var value  in originalValues)
                {
                    if (freshValue.dataElement == value.dataElement)
                    {
                        Assert.AreEqual(value.value, freshValue.value, "Dataset element value does not match");
                        found = true;
                        originalValues.Remove(value);
                        break;
                    }
                }
                Assert.IsTrue(found, "Some dataset elements are missing");
            }
        }

        [TestMethod]
        public void VerifyingSavedData_Monthly_Based_Report()
        {
            var agent = new AuthorizationAgent("admin", "district");
            var baseUrl = "https://apps.dhis2.org/demo";
            var data = new dataValueSet();
            data.dataSet = "Rl58JxmKJo2";   // PMTCT monthly summary
            data.orgUnit = "DiszpKrYNg8";   // Ngelehun CHC
            data.period = "201412";

            // DataValues will be randomly generated
            Random random = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
            var values = new dataValue[] {
                new dataValue
                {
                    dataElement = "u6yhzgWPIsj",    // HIV positive women assessed for ART eligibility by CD4 counting
                    value = random.Next(1, 100).ToString()
                },
                new dataValue
                {
                    dataElement = "CwnEqKR0ebt",    // HIV positive women assessed for ART eligibility by clinical staging
                    //value = random.Next(1, 1000).ToString()
                    value = "19870"
                },
                new dataValue
                {
                    dataElement = "yMtFhLsbZaL",    // PMTCT discordant partners or couples
                    value = random.Next(1, 100).ToString()
                },
                new dataValue
                {
                    dataElement = "ZFC9MdnFHFJ",    // PMTCT expected delivery among HIV+ women
                    value = random.Next(1, 100).ToString()
                },
                new dataValue
                {
                    dataElement = "x0PshcPLSk1",    // PMTCT HIV exposed children registered during the course of the month
                    value = random.Next(1, 100).ToString()
                },
            };
            data.dataValue = values;

            var transferManager = new DataTransferManager(baseUrl, agent);
            var importSummary = transferManager.SendDataValues(data);

            Assert.IsNotNull(importSummary, "Data import failed");
            Assert.AreEqual(importSummary.STATUS_SUCCESS, importSummary.status, importSummary.description);
            Assert.IsNotNull(importSummary.importCount, "Data import count is inconsistent");

            var outputValues = transferManager.GetDataValues(data.dataSet, data.orgUnit, data.period);
            Assert.IsNotNull(outputValues, "Output values can not be null");
            Assert.AreEqual(5, outputValues.dataValue.Length, "Number of data elements don't match");

            var originalValues = data.dataValue.ToList();
            foreach (var freshValue in outputValues.dataValue)
            {
                bool found = false;
                foreach (var value in originalValues)
                {
                    if (freshValue.dataElement == value.dataElement)
                    {
                        Assert.AreEqual(value.value, freshValue.value, "Dataset element value does not match");
                        found = true;
                        originalValues.Remove(value);
                        break;
                    }
                }
                Assert.IsTrue(found, "Some dataset elements are missing");
            }
        }
    }
}
